#include <pcap.h>
#include <netinet/in.h>
#include <arpa/inet.h>
#include <cstring>
#include <iostream>
#include <map>
#include <string>

#include <stdio.h>
#include <netdb.h>
#include <arpa/inet.h>

std::map<std::string, std::string> g_ip2NameMap;
// 打印IP地址
std::string getIp(u_char *ptr)
{
    struct in_addr addr;
    memcpy(&addr.s_addr, ptr, sizeof(in_addr));
    return inet_ntoa(addr);
}

// 回调函数，处理捕获到的数据包
void packet_handler(u_char *args, const struct pcap_pkthdr *header, const u_char *packet)
{
    // 跳过Ethernet头部（14 bytes）
    u_char *payload = (u_char *)(packet + 14);
    // 判断是否是IPV4协议
    if (*payload != 0x45) {
        return;
    }
    // 获取Protocol字段（1 byte）
    u_char protocol = *(payload + 9);
    // 判断是否是TCP协议
    if (protocol != 0x06) {
        return;
    }

    payload += 16;
    struct in_addr addr;
    memcpy(&addr.s_addr, payload, sizeof(in_addr));
    std::string ip = inet_ntoa(addr);
    if (g_ip2NameMap.find(ip) != g_ip2NameMap.end()) {
        std::cout << "acc=>" << g_ip2NameMap[ip] << std::endl;
    }
}
/**
 * 1.多网卡处理
 * 2.域名解析ip
 * 3.捕获单网卡处理
 */
int main(int argc, char **argv)
{
    struct hostent *hptr = gethostbyname("oa.uniontech.com");
    if (hptr == NULL) {
        printf("gethostbyaddr failed\n");
        return 0;
    }

    for (int i = 0; hptr->h_addr_list[i] != NULL; i++) {
        g_ip2NameMap[inet_ntoa(*(struct in_addr *)hptr->h_addr_list[i])] = "oa.uniontech.com";
    }

    pcap_t *handle;
    char errbuf[PCAP_ERRBUF_SIZE];
    bpf_u_int32 net;
    bpf_u_int32 mask;

    // 获取默认网卡的IP地址和子网掩码
    pcap_lookupnet("eno1", &net, &mask, errbuf);

    // 打开网卡，设置混杂模式和过滤规则（捕获TCP端口为80或443的流量）
    handle = pcap_open_live("eno1", BUFSIZ, 1, 1000, errbuf);
    struct bpf_program fp;
    char filter_exp[] = "tcp port 80 or tcp port 443";
    pcap_compile(handle, &fp, filter_exp, 0, net);
    pcap_setfilter(handle, &fp);

    // 循环捕获数据包，直到用户中断程序
    pcap_loop(handle, -1, packet_handler, NULL);

    pcap_breakloop(handle);

    return 0;
}
